#include "src/scene/mask.h"

#include <iostream>

#include "src/defines/filterType.h"

Mask::Mask(int _r, int _c) : m(_r), n(_c){
    alloc();
}

Mask::~Mask(){
	for(int i = 0; i < m; i++){
		delete[] mask[i];
		delete[] color[i];
    }
	delete[] mask;
	delete[] color;
}

void Mask::alloc()
{
    mask = new double*[m];
    color = new Color*[m];
    for(int i = 0; i < m; i++){
        mask[i] = new double[n];
        color[i] = new Color[n];
    }
}

Color Mask::getColor() const{
    Color result (0, 0, 0, 0);
    double weight = 0;

//    bool in = false;
    for(int i = 0; i < m; i++){
        for(int j = 0; j < n; j++){
            result = result + (color[i][j] * mask[i][j]);
            weight += mask[i][j];
//            if(color[i][j] != Color()){
//            std::cout << "\tcolor "; (color[i][j]* mask[i][j]).print();
////            std::cout << "\tresutant "; result.print();
////            std::cout << "\tweight " << weight << std::endl;
//            in = true;
//            }
        }
    }

    result = result / weight;
//    if(in){std::cout << "\t\tresutant final"; result.print();
//    std::cout << "\t\tresutant final TRUNCADA"; result.truncate().print();}
    return result.truncate();
}

void Mask::gaussian(double _sigma){
    int a = getA();
    int b = getB();
    double sigma_2 = _sigma * _sigma, i_2, j_2;
    for(int i = -a; i <= a; i++){
        for(int j = -b; j <= b; j++){
            i_2 = i*i;
            j_2 = j*j;
            mask[i + a][j + b] = pow(M_E, -(i_2 + j_2)/(2*sigma_2));
        }
    }
}

void Mask::laplacian(int _neighborhood, int _negative){
    if (_negative == 0) _negative = -1;

    if(_neighborhood == 0){//vizinhança 4
        mask[0][0] = mask[2][2] = mask[0][2] = mask[2][0] = 0.0;
        mask[1][0] = mask[0][1] = mask[1][2] = mask[2][1] = -1 * _negative;
        mask[1][1] = 4 * _negative;
    }else{
        mask[0][0] = mask[2][2] = mask[0][2] = mask[2][0] = -0.25 * _negative;
        mask[1][0] = mask[0][1] = mask[1][2] = mask[2][1] = -0.5 * _negative;
        mask[1][1] = 3 * _negative;
    }
}

void Mask::weightedAverage(){
    int power;
    int a = getA();
    int b = getB();
    for(int i = -a; i <= a; i++){
        for(int j = -b; j <= b; j++){
            power = a + b - (fabs(i) + fabs(j));
            mask[i + a][j + b] = pow(2, power);
        }
    }
}

void Mask::mean(){
    for(int i = 0; i < m; i++){
        for(int j = 0; j < n; j++){
            mask[i][j] = 1.0;
        }
    }
}

void Mask::print(){
    std::cout << "Mascara " << m << " x " << n << std::endl;

    for(int i = 0; i < m; i++){
        for(int j = 0; j < n; j++){
            std::cout << mask[i][j] << "\t";
        }
        std::cout << std::endl;
    }
}
